package com.example.road;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatImageButton;

import android.Manifest;
import android.app.AlertDialog;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;
import android.widget.Toast;

import com.cn.jerey.permissiontools.Callback.PermissionCallbacks;
import com.cn.jerey.permissiontools.PermissionTools;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.mapbox.android.core.permissions.PermissionsManager;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.LineString;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.location.LocationComponent;
import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions;
import com.mapbox.mapboxsdk.location.LocationComponentOptions;
import com.mapbox.mapboxsdk.location.modes.CameraMode;
import com.mapbox.mapboxsdk.location.modes.RenderMode;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity implements MapboxMap.OnMapClickListener, SearchView.OnQueryTextListener, AdapterView.OnItemClickListener {
    private MapView mapView;
    private MapboxMap map;
    private List<LatLng> points;
    private final static String BASE_URL = "http://192.168.2.14:4567/";
    private final static String TAG = "测试";
    private Style mapStyle;
    private final static String ID_SOURCE="line-source";
    private final static String ID_LAYER="line-id";
    private ListView listView;
    private ArrayList<String> list;   //数据缓存
    private AppCompatImageButton showImageButton;
    private String roadInfo;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Mapbox.getInstance(this, getString(R.string.mapbox_access_token));
        setContentView(R.layout.activity_main);
        mapView = (MapView) findViewById(R.id.mapView);
        mapView.onCreate(savedInstanceState);
        points=new ArrayList<>();

        mapView.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(@NonNull MapboxMap mapboxMap) {
                map=mapboxMap;
                mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
                    @Override
                    public void onStyleLoaded(@NonNull Style style) {

                        // Map is set up and the style has loaded. Now you can add data or make other map adjustments
                      map.addOnMapClickListener(MainActivity.this::onMapClick);
                      CameraPosition cameraPosition=new CameraPosition.Builder().target(new LatLng(30.5008,114.2222)).zoom(15).build();
                      map.setCameraPosition(cameraPosition);
                      mapStyle=style;

                    }
                });

            }
        });
        askPermission();
        listView=findViewById(R.id.list);
        listView.setOnItemClickListener(this);
        SearchView searchView = findViewById(R.id.searchView);
        searchView.onActionViewExpanded();
        searchView.setOnQueryTextListener(this);  //为查询文本框注册监听器
        showImageButton=findViewById(R.id.roadInfo);
        showImageButton.setEnabled(false);

    }
    @SuppressWarnings( {"MissingPermission"})
    private void enableLocationComponent(@NonNull Style loadedMapStyle) {
        if (PermissionsManager.areLocationPermissionsGranted(this)) {
            LocationComponentOptions customLocationComponentOptions = LocationComponentOptions.builder(this)
                    .pulseEnabled(true)
                    .build();

            LocationComponent locationComponent = map.getLocationComponent();


            locationComponent.activateLocationComponent(
                    LocationComponentActivationOptions.builder(this, loadedMapStyle)
                            .locationComponentOptions(customLocationComponentOptions)
                            .build());

            locationComponent.setLocationComponentEnabled(true);

            locationComponent.setCameraMode(CameraMode.TRACKING);

            locationComponent.setRenderMode(RenderMode.NORMAL);
        } else {
            askPermission();
        }
    }
    /**
     * 动态申请权限
     */
    private void askPermission(){
        PermissionTools permissionTools;

        permissionTools =  new PermissionTools.Builder(this)
                .setOnPermissionCallbacks(new PermissionCallbacks() {
                    @Override
                    public void onPermissionsGranted(int requestCode, List<String> perms) {
                        Toast.makeText(MainActivity.this,"权限申请通过",Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onPermissionsDenied(int requestCode, List<String> perms) {
                        Toast.makeText(MainActivity.this,"权限申请被拒绝",Toast.LENGTH_SHORT).show();
                    }
                })
                .setRequestCode(111)
                .build();
        permissionTools.requestPermissions(Manifest.permission.ACCESS_FINE_LOCATION);
        permissionTools.requestPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mapView.onStart();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
        mapView.onStop();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapView.onLowMemory();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }

    @Override
    public boolean onMapClick(@NonNull LatLng point) {

        map.addMarker(new MarkerOptions()
                .position(new LatLng(point.getLatitude(), point.getLongitude()))
                .title("经度："+point.getLongitude()+"\n"+"纬度："+point.getLatitude()));
        points.add(point);
        return false;
    }

    public void clear(View view) {
        points.clear();
        map.clear();
        clearLine();
        showImageButton.setEnabled(false);
    }
    //清除线
    private void clearLine(){
        if(mapStyle.getLayer(ID_LAYER)!=null){
            mapStyle.removeLayer(ID_LAYER);
        }
        if(mapStyle.getSource(ID_SOURCE)!=null){
            mapStyle.removeSource(ID_SOURCE);
        }
    }
    private void showRoad(String jsonText){
        try {
            Gson gson =new GsonBuilder().serializeNulls().create();
            RouteResult json = gson.fromJson(jsonText,RouteResult.class);
            if(json.getRouting_success()){
                Toast.makeText(MainActivity.this,"路径规划成功",Toast.LENGTH_SHORT).show();
            }
            List<Point> routeCoordinates=new ArrayList<>();
            for (int i = 0; i <json.getRoute().size() ; i++) {
                TempPoint tempPoint=json.getRoute().get(i);
                routeCoordinates.add(Point.fromLngLat(tempPoint.getLon(), tempPoint.getLat()));
            }

            clearLine();
            mapStyle.addSource(new GeoJsonSource(ID_SOURCE,
                    FeatureCollection.fromFeatures(new Feature[] {Feature.fromGeometry(
                            LineString.fromLngLats(routeCoordinates)
                    )})));


            mapStyle.addLayer(new LineLayer(ID_LAYER, ID_SOURCE).withProperties(
                    PropertyFactory.lineDasharray(new Float[] {0.01f, 2f}),
                    PropertyFactory.lineCap(Property.LINE_CAP_ROUND),
                    PropertyFactory.lineJoin(Property.LINE_JOIN_ROUND),
                    PropertyFactory.lineWidth(5f),
                    PropertyFactory.lineColor(Color.parseColor("#e55e5e"))
            ));
            roadInfo=json.getDirections().replaceAll("<br>","\n");
            showImageButton.setEnabled(true);
        }catch (Exception e){
            Log.d(TAG, "failure: "+e.getMessage());

        }
    }
    /**
     * 路径查询
     * @param view
     */
    public void queryRoad(View view) {
        if(points.size()<2){
            Toast.makeText(MainActivity.this,"请线选择起点和终点",Toast.LENGTH_SHORT).show();
            return;
        }
        int size=points.size();
        OkHttpClient okHttpClient = new OkHttpClient();
        String url = BASE_URL +
                "/route?start_lon=" + points.get(size - 2).getLongitude() +
                "&start_lat=" + points.get(size - 2).getLatitude() +
                "&end_lon=" + points.get(size - 1).getLongitude() +
                "&end_lat=" + points.get(size - 1).getLatitude();
        final Request request = new Request.Builder()
                .url(url)
                .get()//默认就是GET请求，可以不写
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d(TAG, "onFailure: "+e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result=response.body().string();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        showRoad(result);
                    }
                });
            }
        });
    }

    public void startLocate(View view) {
        enableLocationComponent(mapStyle);

    }

    @Override
    public boolean onQueryTextSubmit(String s) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String s) {
        list = new ArrayList<String>();
        if(!TextUtils.isEmpty(s)){
            OkHttpClient okHttpClient = new OkHttpClient();
            String url = BASE_URL +
                    "/search?term=" + s;
            final Request request = new Request.Builder()
                    .url(url)
                    .get()//默认就是GET请求，可以不写
                    .build();
            Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.d(TAG, "onFailure: "+e.getMessage());
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    String result=response.body().string();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Gson gson =new GsonBuilder().serializeNulls().create();
                            List<String> json = gson.fromJson(result,new TypeToken<List<String>>() {}.getType());
                            list= (ArrayList<String>) json;
                            updateList();
                        }
                    });
                }
            });
        }else {
            updateList();
        }

        return false;
    }
    private void updateList(){
        ArrayAdapter listAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,list);//创建适配器与数据源showlist绑定
        listView.setAdapter(listAdapter);
    }



    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
       String key=list.get(i);
        OkHttpClient okHttpClient = new OkHttpClient();
        String url = BASE_URL +
                "/search?full=true&term=" + key;
        final Request request = new Request.Builder()
                .url(url)
                .get()//默认就是GET请求，可以不写
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d(TAG, "onFailure: "+e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result=response.body().string();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Gson gson =new GsonBuilder().serializeNulls().create();
                        List<InPoint> results = gson.fromJson(result,new TypeToken<List<InPoint>>() {}.getType());
                        showResult(results);
                    }
                });
            }
        });
        Log.e(TAG,key);

        //清空下拉列表
       onQueryTextChange("");
    }

    private void showResult(List<InPoint> results) {
        clear(null);
        if(results.size()==0){
            return;
        }
        double latMin=results.get(0).getLat();
        double latMax=results.get(0).getLat();
        double lonMin=results.get(0).getLon();
        double lonMax=results.get(0).getLon();
        for (int i = 0; i <results.size() ; i++) {
            InPoint point=results.get(i);
            map.addMarker(new MarkerOptions()
                    .position(new LatLng(point.getLat(), point.getLon()))
                    .title("名称："+point.getName()+"\n"+"经度："+point.getLon()+"\n"+"纬度："+point.getLat()));


            if(latMax<point.getLat()){
                latMax=point.getLat();
            } if(lonMax<point.getLon()){
                lonMax=point.getLon();
            } if(latMin>point.getLat()){
                latMin=point.getLat();
            } if(lonMin>point.getLon()){
                lonMin=point.getLon();
            }

        }
        LatLngBounds latLngBounds=LatLngBounds.from(latMin,lonMin,latMax,lonMax);
        CameraPosition cameraPosition=   map.getCameraForLatLngBounds(latLngBounds);
        map.setCameraPosition(cameraPosition);
    }

    public void showInfo(View view) {
           new AlertDialog.Builder(MainActivity.this).setMessage(roadInfo).create().show();
    }
}